package org.example.promise.usage;

import org.example.promise.Promise;

import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 类描述：Promise 的应用---下载一个文件并计算行数
 * <br>
 *
 * @author ZS
 * @version 1.0
 * @date 2020/12/29
 **/
public class App {
    private static final String DEFAULT_URL =
            "https://github.com/ZhSMM/java-design-patterns/blob/master/abstract-document/pom.xml";
    private final ExecutorService executor;
    private final CountDownLatch stopLatch;

    public App() {
        this.executor = Executors.newFixedThreadPool(2);
        this.stopLatch = new CountDownLatch(2);
    }

    public static void main(String[] args) throws InterruptedException {
        App app = new App();
        try {
            app.promiseUsage();
        } finally {
            app.stop();
        }
    }

    private void promiseUsage() {
        calculateLineCount();
        calculateLowestFrequency();
    }

    private void calculateLowestFrequency() {
        lowestFrequencyChar().thenAccept(character -> {
            System.out.println("出现最少的字符：" + character);
            taskCompleted();
        });
    }

    private void calculateLineCount() {
        countLines().thenAccept(lines -> {
            System.out.println("文件行数：" + lines);
            taskCompleted();
        });
    }

    private Promise<Optional<Character>> lowestFrequencyChar() {
        return characterFrequency().thenApply(Utility::lowestFrequencyChar);
    }

    private Promise<Map<Character, Long>> characterFrequency() {
        return download(DEFAULT_URL).thenApply(Utility::characterFrequency);
    }

    private Promise<Integer> countLines() {
        return download(DEFAULT_URL).thenApply(Utility::countLines);
    }

    // 异步下载
    private Promise<String> download(String urlString) {
        return new Promise<String>()
                .fulfillInAsync(() -> Utility.downloadFile(urlString), executor)
                .onError(throwable -> {
                    throwable.printStackTrace();
                    taskCompleted();
                });
    }

    private void taskCompleted() {
        // 相当于计数器建一
        stopLatch.countDown();
    }

    // 关闭
    private void stop() throws InterruptedException {
        stopLatch.await();
        executor.shutdownNow();
    }
}
